diff options
Diffstat (limited to 'src2/pages/my/transaction/[id].js')
| -rw-r--r-- | src2/pages/my/transaction/[id].js | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/src2/pages/my/transaction/[id].js b/src2/pages/my/transaction/[id].js new file mode 100644 index 00000000..fb806aa4 --- /dev/null +++ b/src2/pages/my/transaction/[id].js @@ -0,0 +1,265 @@ +import AppBar from "@/components/layouts/AppBar"; +import Layout from "@/components/layouts/Layout"; +import LineDivider from "@/components/elements/LineDivider"; +import WithAuth from "@/components/auth/WithAuth"; +import { useCallback, useEffect, useRef, useState } from "react"; +import apiOdoo from "@/core/utils/apiOdoo"; +import { useRouter } from "next/router"; +import { useAuth } from "@/core/utils/auth"; +import currencyFormat from "@/core/utils/currencyFormat"; +import DescriptionRow from "@/components/elements/DescriptionRow"; +import { TransactionDetailAddress } from "@/components/transactions/TransactionDetail"; +import { SkeletonList } from "@/components/elements/Skeleton"; +import Link from "@/components/elements/Link"; +import { ChevronRightIcon } from "@heroicons/react/24/outline"; +import Alert from "@/components/elements/Alert"; +import TransactionStatusBadge from "@/components/transactions/TransactionStatusBadge"; +import useConfirmAlert from "@/lib/elements/hooks/useConfirmAlert"; +import { toast } from "react-hot-toast"; +import useBottomPopup from "@/lib/elements/hooks/useBottomPopup"; +import getFileBase64 from "@/core/utils/getFileBase64"; +import VariantGroupCard from "@/components/variants/VariantGroupCard"; + +export default function DetailTransaction() { + const router = useRouter(); + const { id } = router.query; + const [ auth ] = useAuth(); + const [ transaction, setTransaction ] = useState(null); + + const loadTransaction = useCallback(async () => { + if (auth && id) { + const dataTransaction = await apiOdoo('GET', `/api/v1/partner/${auth?.partner_id}/sale_order/${id}`); + setTransaction(dataTransaction); + } + }, [ auth, id ]); + + useEffect(() => { + loadTransaction(); + }, [ loadTransaction ]); + + const submitCancelTransaction = async (data) => { + const isCancelled = await apiOdoo('POST', `/api/v1/partner/${auth.partner_id}/sale_order/${data.id}/cancel`); + if (isCancelled) { + toast.success('Berhasil batalkan transaksi'); + loadTransaction(); + } + } + + const { + openConfirmAlert, + ConfirmAlert + } = useConfirmAlert({ + title: 'Batalkan Transaksi', + caption: 'Apakah anda yakin untuk membatalkan transaksi?', + closeText: 'Tidak', + submitText: 'Iya, batalkan', + onSubmit: submitCancelTransaction + }); + + const UploadPurchaseOrder = () => { + const nameRef = useRef(''); + const fileRef = useRef(''); + + const submitUploadPurchaseOrder = async (e) => { + e.preventDefault(); + const file = fileRef.current.files[0]; + const name = nameRef.current.value; + if (file.size > 5000000) { + toast.error('Maksimal ukuran file adalah 5MB', { + position: 'bottom-center' + }); + return; + } + const parameter = { + name, + file: await getFileBase64(file) + }; + const isUploaded = await apiOdoo('POST', `/api/v1/partner/${auth.partner_id}/sale_order/${transaction.id}/upload_po`, parameter); + if (isUploaded) { + toast.success('Berhasil upload PO'); + loadTransaction(); + closePopup(); + } + }; + + return ( + <form className="flex flex-col gap-y-4" onSubmit={submitUploadPurchaseOrder}> + <div> + <label className="form-label mb-2">Nama PO</label> + <input className="form-input" type="text" ref={nameRef} required /> + </div> + <div> + <label className="form-label mb-2">Dokumen PO</label> + <input className="form-input" type="file" ref={fileRef} required /> + </div> + <button type="submit" className="btn-yellow w-full mt-2">Upload</button> + </form> + ); + } + + const { + closePopup, + BottomPopup, + openPopup + } = useBottomPopup({ + title: 'Upload PO', + children: UploadPurchaseOrder + }); + + const downloadPurchaseOrder = () => { + const url = `${process.env.ODOO_HOST}/api/v1/partner/${auth.partner_id}/sale_order/${transaction.id}/download_po/${transaction.token}`; + window.open(url, 'download') + }; + + const downloadQuotation = () => { + const url = `${process.env.ODOO_HOST}/api/v1/partner/${auth.partner_id}/sale_order/${transaction.id}/download/${transaction.token}`; + window.open(url, 'download') + }; + + const checkout = async () => { + if (!transaction.purchase_order_file) { + toast.error('Mohon upload dokumen PO anda sebelum melanjutkan pesanan') + return + } + await apiOdoo('POST', `/api/v1/partner/${auth?.partner_id}/sale_order/${id}/checkout`) + toast.success('Berhasil melanjutkan pesanan') + loadTransaction() + } + + return ( + <WithAuth> + <Layout className="pb-4"> + <AppBar title="Detail Transaksi" /> + + { transaction ? ( + <> + <div className="p-4 flex flex-col gap-y-4"> + <DescriptionRow label="Status Transaksi"> + <div className="flex justify-end"> + <TransactionStatusBadge status={transaction?.status} /> + </div> + </DescriptionRow> + <DescriptionRow label="No Transaksi"> + { transaction?.name } + </DescriptionRow> + <DescriptionRow label="Ketentuan Pembayaran"> + { transaction?.payment_term } + </DescriptionRow> + <DescriptionRow label="Nama Sales"> + { transaction?.sales } + </DescriptionRow> + <DescriptionRow label="Waktu Transaksi"> + { transaction?.date_order } + </DescriptionRow> + </div> + + <LineDivider /> + + <div className="p-4 flex flex-col gap-y-4"> + <DescriptionRow label="Purchase Order"> + { transaction?.purchase_order_name || '-' } + </DescriptionRow> + <div className="flex items-center"> + <p className="text-gray_r-11 leading-none">Dokumen PO</p> + <button + type="button" + className="btn-light py-1.5 px-3 ml-auto" + onClick={transaction?.purchase_order_file ? downloadPurchaseOrder : openPopup} + > + { transaction?.purchase_order_file ? 'Download' : 'Upload' } + </button> + </div> + </div> + + <LineDivider /> + + <p className="h2 p-4">Detail Produk</p> + + <div className="mt-2 p-4 pt-0 flex flex-col gap-y-3"> + <VariantGroupCard + variants={transaction?.products} + buyMore + /> + <div className="flex justify-between mt-3 font-medium"> + <p>Total Belanja</p> + <p>{ currencyFormat(transaction?.amount_total || 0) }</p> + </div> + </div> + + <LineDivider /> + + <TransactionDetailAddress transaction={transaction} /> + + <LineDivider /> + + <div className="p-4"> + <p className="h2">Invoice</p> + <div className="flex flex-col gap-y-3 mt-4"> + { transaction?.invoices?.map((invoice, index) => ( + <Link href={`/my/invoice/${invoice.id}`} key={index}> + <div className="shadow rounded-md p-4 text-gray_r-12 font-normal flex justify-between"> + <div> + <p className="mb-2">{ invoice?.name }</p> + <div className="flex items-center gap-x-1"> + { invoice.amount_residual > 0 ? ( + <div className="badge-red">Belum Lunas</div> + ) : ( + <div className="badge-green">Lunas</div> + ) } + <p className="text-caption-2 text-gray_r-11"> + { currencyFormat(invoice.amount_total) } + </p> + </div> + </div> + <ChevronRightIcon className="w-5 stroke-2" /> + </div> + </Link> + )) } + { transaction?.invoices?.length === 0 && ( + <Alert type='info' className='text-center'> + Belum ada Invoice + </Alert> + ) } + </div> + </div> + + <LineDivider /> + + <div className="px-4"> + { transaction?.status == 'draft' && ( + <button + className="btn-yellow w-full mt-4" + onClick={checkout} + > + Lanjutkan Transaksi + </button> + ) } + <button + className="btn-light w-full mt-4" + disabled={transaction?.status != 'draft'} + onClick={downloadQuotation} + > + Download Quotation + </button> + { transaction?.status != 'draft' && ( + <button + className="btn-light w-full mt-4" + disabled={transaction?.status != 'waiting'} + onClick={() => openConfirmAlert(transaction)} + > + Batalkan Transaksi + </button> + ) } + </div> + </> + ) : ( + <div className="p-4 py-6"> + <SkeletonList number={12} /> + </div> + ) } + { ConfirmAlert } + { BottomPopup } + </Layout> + </WithAuth> + ); +}
\ No newline at end of file |
